package handler.wx

import org.apache.commons.codec.digest.DigestUtils

import service.wx.WxSignature
import service.wx.WxMessager
import service.wx.WxApi
import service.wx.WxUserLocal

import util.Utils

handler.get('/wx/refresh'){req, resp ->
	WxSignature.refreshConf()
	resp.end 'ok'
}

// 公众号服务提供的接入验证
// refer http://mp.weixin.qq.com/wiki/17/2d4265491f12608cd170a95559800f2d.html
handler.get('/wx/token'){req, resp ->
	String s = req.params.signature
	String t = req.params.timestamp
	String n = req.params.nonce

	String echostr = req.params.echostr

	final String token = 'paic1234'

	List ll = [token, t, n]
	ll.sort()
	log.info('' + ll)

	String str = ll.join('')
	str = DigestUtils.shaHex(str)

	boolean isCheckOk = s == str
	if(isCheckOk)
		resp.end echostr
	else
		resp.end 'fail'
}

// 公众号服务普通消息的dispatcher
// refer http://mp.weixin.qq.com/wiki/10/79502792eef98d6e0c6e1739da387346.html
/**
eg. 
// 关注事件
WxMessager.inst.add('event', 'subscribe'){Map<String, String> info -> 
	String userName = info.FromUserName
	String c = """
	欢迎订阅！

	userName
	"""
	[MsgType: 'text', Content: c]
}

WxMessager.inst.add('text', /\:.+/){Map<String, String> info -> 
	log.info(info.FromUserName + ' - ' + info.Content)
	String c = """
		Ok，我们会回复你的！
	"""
	[MsgType: 'text', Content: c]
}
*/
handler.post('/wx/token'){req, resp ->
	// 接收xml
	req.bodyHandler{body -> 
		final String encoding  = 'utf-8'
		XmlParser parser = new XmlParser()

		try{
		// *** try begin
   
		// 解析xml
		def root = parser.parseText(new String(body.bytes, encoding))

		Map<String, String> info = [:]
		info.ToUserName = root.ToUserName.text()
		info.FromUserName = root.FromUserName.text()
		info.CreateTime = root.CreateTime.text()

		info.MsgType = root.MsgType.text()
		info.MsgId = root.MsgId.text()

		if('text' == info.MsgType){
			info.Content = root.Content.text()
		}else if('image' == info.MsgType){
			info.PicUrl = root.PicUrl.text()
			info.MediaId = root.MediaId.text()
		}else if('voice' == info.MsgType){
			info.Format = root.Format.text()
		}else if('video' == info.MsgType){
			info.ThumbMediaId = root.ThumbMediaId.text()
		}else if('location' == info.MsgType){
			info.Location_X = root.Location_X.text()
			info.Location_Y = root.Location_Y.text()
			info.Scale = root.Scale.text()
			info.Label = root.Label.text()
		}else if('link' == info.MsgType){
			info.Title = root.Title.text()
			info.Description = root.Description.text()
			info.Url = root.Url.text()
		}else if('event' == info.MsgType){
			info.Event = root.Event.text()
			info.EventKey = root.EventKey.text()
		}else{
		}

		log.info('wx info : ' + info)

		// command模式，处理信息
		Map<String, String> result = WxMessager.inst.process(info)
		if(!result){
			resp.end ''
			return
		}
		// 返回给发送者，调换openid
		result.ToUserName = info.FromUserName
		result.FromUserName = info.ToUserName

		// 返回xml
		def sw = new StringWriter()
		def builder = new groovy.xml.MarkupBuilder(sw)
		String[] keys = ['ToUserName', 'FromUserName', 'MsgType', 
			'Content', 'PicUrl', 'Location_X', 'Location_Y', ,'Scale', 'Label', 
			'Title', 'Description', 'Url']
		builder.xml{
			CreateTime('' + new Date().getTime())

			for(key in keys){
				if(result[key]){
			"${key}"(result[key])
				}
			}
		}

		String returnStr = sw.toString()
		log.info('back message - ' + returnStr)
		resp.end(returnStr)

		// *** try end
		}catch(ex){
			log.error('wx info error!', ex)
			resp.end ''
		}
	}
}

// 用户登录
handler.get('/wx/auth'){req, resp ->
	String ua = req.headers.get('User-Agent')
	boolean isWx = WxApi.isReqFromWx(ua)

	String targetUri = req.params.targetUri ?: '/wx/auth-redirect-target?1=1'
	String redirectUri = req.params.redirectUri

	if(!redirectUri){
		def uri = req.absoluteURI
		redirectUri = uri.scheme + '://' + uri.host + 
			'/wx/auth-redirect-test?1=1' + 
			'&target_uri=' + targetUri
	}
	if(!isWx){
		log.info('not from weixin - ' + ua)
		String testOpenid = WxSignature.conf.testOpenid

		log.info('redirect - ' + redirectUri + '&openid=' + testOpenid)
		resp.redirect(redirectUri + '&openid=' + testOpenid)
		return
	}

	redirectUri = URLEncoder.encode(redirectUri)
	String appid = WxSignature.conf.appid
	String authUrl = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=${appid}&redirect_uri=${redirectUri}&response_type=code&scope=snsapi_base&state=STATE#wechat_redirect"

	// 一周内如果之前有授权过，就直接从缓存到本地库里去取
	String openid = req.params.openid
	if(openid){
		final long expire = 3600 * 24 * 7
		String user = WxUserLocal.getUserByOpenid(openid, expire)
		if(user == null){
			resp.redirect(authUrl)
		}else{
			resp.redirect(targetUri + '&' + Utils.generateQueryString(user, 'openid,nickname,province,city,sex,headimgurl'))
		}
	}else{
		log.info('redirect - ' + authUrl)
		resp.redirect(authUrl)
	}
}

handler.get('/wx/auth-redirect-target'){req, resp ->
	// 异常
	if(req.params.errcode){
		resp.end('' + req.params.errcode + ' - ' + req.params.errmsg)
		return
	}

	if(req.params.reject){
		resp.end('reject')
		return
	}

	Map user = Utils.getMapInKeys(req.params, 'openid,nickname,province,city,sex,headimgurl')
	resp.json(user)
}

// 微信授权登录后获取用户信息
handler.get('/wx/auth-redirect-test'){req, resp ->
	String code = req.params.code
	String targetUri = req.params.targetUri ?: '/wx/auth-redirect-target?1=1'

	if(code){
		def info = WxSignature.getAccessTokenInfo4Auth(code)
		if(info.errcode){
			resp.redirect(targetUri + '&' + Utils.generateQueryString(info, 'errcode,errmsg'))
			return
		}

		def user = WxApi.getUserInfo4Auth(info.access_token, info.openid)
		if(user.errcode){
			resp.redirect(targetUri + '&' + Utils.generateQueryString(user, 'errcode,errmsg'))
			return
		}

		WxUserLocal.update(user)
		resp.redirect(targetUri + '&' + Utils.generateQueryString(user, 'openid,nickname,province,city,sex,headimgurl'))
	}else{
		resp.redirect(targetUri + '&reject=1')
	}
}